/*
 * Copyright (c) 2006-2020, RT-Thread Development Team
 *
 * SPDX-License-Identifier: Apache-2.0
 *
 * Change Logs:
 * Date           Author       Notes
 * 2020-12-10     sj-wd       the first version
 */
#include "board.h"
#include "drv_common.h"

void rt_tft_io_init(void);

#define TFT_W 320
#define TFT_H 240
#define BLACK       0x0000

#define LCD_RS_CLR  HAL_GPIO_WritePin(GPIOB,GPIO_PIN_0,GPIO_PIN_RESET);
#define LCD_RS_SET  HAL_GPIO_WritePin(GPIOB,GPIO_PIN_0,GPIO_PIN_SET);
#define LCD_RE_CLR  HAL_GPIO_WritePin(GPIOB,GPIO_PIN_2,GPIO_PIN_RESET);
#define LCD_RE_SET  HAL_GPIO_WritePin(GPIOB,GPIO_PIN_2,GPIO_PIN_SET);

SPI_HandleTypeDef hspi4;

void rt_tft_spi_init(void)
{
    GPIO_InitTypeDef GPIO_InitStruct = {0};

    __HAL_RCC_SPI4_CLK_ENABLE();
    __HAL_RCC_GPIOE_CLK_ENABLE();

    GPIO_InitStruct.Pin = GPIO_PIN_2|GPIO_PIN_5|GPIO_PIN_6;
    GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
    GPIO_InitStruct.Pull = GPIO_NOPULL;
    GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
    GPIO_InitStruct.Alternate = GPIO_AF5_SPI4;
    HAL_GPIO_Init(GPIOE, &GPIO_InitStruct);

    hspi4.Instance = SPI4;
    hspi4.Init.Mode = SPI_MODE_MASTER;
    hspi4.Init.Direction = SPI_DIRECTION_2LINES;
    hspi4.Init.DataSize = SPI_DATASIZE_8BIT;
    hspi4.Init.CLKPolarity = SPI_POLARITY_LOW;
    hspi4.Init.CLKPhase = SPI_PHASE_1EDGE;
    hspi4.Init.NSS = SPI_NSS_SOFT;
    hspi4.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_2;
    hspi4.Init.FirstBit = SPI_FIRSTBIT_MSB;
    hspi4.Init.TIMode = SPI_TIMODE_DISABLE;
    hspi4.Init.CRCCalculation = SPI_CRCCALCULATION_DISABLE;
    hspi4.Init.CRCPolynomial = 0x0;
    if (HAL_SPI_Init(&hspi4) != HAL_OK)
    {
    //Error_Handler();
    }
    rt_tft_io_init();
}

void rt_tft_io_init(void)
{
    GPIO_InitTypeDef GPIO_InitStruct = {0};

    __HAL_RCC_GPIOB_CLK_ENABLE();

    GPIO_InitStruct.Pin = GPIO_PIN_2|GPIO_PIN_0;
    GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
    GPIO_InitStruct.Pull = GPIO_NOPULL;
    GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
    HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
}

void TFT_WR_REG(uint8_t data){
  LCD_RS_CLR;
  HAL_SPI_Transmit(&hspi4,&data,1,0xffff);
}

void TFT_WR_DATA(uint8_t data){
  LCD_RS_SET;
  HAL_SPI_Transmit(&hspi4,&data,1,0xffff);
}

void TFT_WriteReg(uint8_t TFT_Reg, uint16_t TFT_RegValue){
    TFT_WR_REG(TFT_Reg);
    TFT_WR_DATA(TFT_RegValue);
}

void TFT_WriteRAM_Prepare(void){
    TFT_WR_REG(0x2C);
}

void TFT_WriteData_16Bit(uint16_t Data){
   uint8_t da1;
   uint8_t da2;

   LCD_RS_SET;
   da1 = Data >> 8;
   da2 = Data & 0x00FF;
   HAL_SPI_Transmit(&hspi4,&da1,1,0xffff);
   HAL_SPI_Transmit(&hspi4,&da2,1,0xffff);
}

void TFT_SetWindows(uint16_t xStar, uint16_t yStar,uint16_t xEnd,uint16_t yEnd){
    TFT_WR_REG(0x2A);
    TFT_WR_DATA(xStar>>8);
    TFT_WR_DATA(0x00FF&xStar);
    TFT_WR_DATA(xEnd>>8);
    TFT_WR_DATA(0x00FF&xEnd);

    TFT_WR_REG(0x2B);
    TFT_WR_DATA(yStar>>8);
    TFT_WR_DATA(0x00FF&yStar);
    TFT_WR_DATA(yEnd>>8);
    TFT_WR_DATA(0x00FF&yEnd);

    TFT_WriteRAM_Prepare();
}

void TFT_SetCursor(uint16_t Xpos, uint16_t Ypos){
    TFT_SetWindows(Xpos,Ypos,Xpos,Ypos);
}

void TFT_Clear(uint16_t Color){
  unsigned int i,m;
    TFT_SetWindows(0,0,320-1,240-1);
    for(i=0;i<240;i++)
    {
    for(m=0;m<320;m++)
    {
            TFT_WriteData_16Bit(Color);
        }
    }
}

void rt_tft_init(void){
    LCD_RE_SET;
    HAL_Delay(50);
    LCD_RE_CLR;
    HAL_Delay(50);
    LCD_RE_SET;
    HAL_Delay(50);
    TFT_WR_REG(0xCF);
    TFT_WR_DATA(0x00);
    TFT_WR_DATA(0xC9); //C1
    TFT_WR_DATA(0X30);
    TFT_WR_REG(0xED);
    TFT_WR_DATA(0x64);
    TFT_WR_DATA(0x03);
    TFT_WR_DATA(0X12);
    TFT_WR_DATA(0X81);
    TFT_WR_REG(0xE8);
    TFT_WR_DATA(0x85);
    TFT_WR_DATA(0x10);
    TFT_WR_DATA(0x7A);
    TFT_WR_REG(0xCB);
    TFT_WR_DATA(0x39);
    TFT_WR_DATA(0x2C);
    TFT_WR_DATA(0x00);
    TFT_WR_DATA(0x34);
    TFT_WR_DATA(0x02);
    TFT_WR_REG(0xF7);
    TFT_WR_DATA(0x20);
    TFT_WR_REG(0xEA);
    TFT_WR_DATA(0x00);
    TFT_WR_DATA(0x00);
    TFT_WR_REG(0xC0);    //Power control
    TFT_WR_DATA(0x1B);   //VRH[5:0]
    TFT_WR_REG(0xC1);    //Power control
    TFT_WR_DATA(0x00);   //SAP[2:0];BT[3:0] 01
    TFT_WR_REG(0xC5);    //VCM control
    TFT_WR_DATA(0x30);   //3F
    TFT_WR_DATA(0x30);   //3C
    TFT_WR_REG(0xC7);    //VCM control2
    TFT_WR_DATA(0XB7);
    TFT_WR_REG(0x36);    // Memory Access Control
    TFT_WR_DATA(0x08);
    TFT_WR_REG(0x3A);
    TFT_WR_DATA(0x55);
    TFT_WR_REG(0xB1);
    TFT_WR_DATA(0x00);
    TFT_WR_DATA(0x1A);
    TFT_WR_REG(0xB6);    // Display Function Control
    TFT_WR_DATA(0x0A);
    TFT_WR_DATA(0xA2);
    TFT_WR_REG(0xF2);    // 3Gamma Function Disable
    TFT_WR_DATA(0x00);
    TFT_WR_REG(0x26);    //Gamma curve selected
    TFT_WR_DATA(0x01);
    TFT_WR_REG(0xE0);    //Set Gamma
    TFT_WR_DATA(0x0F);
    TFT_WR_DATA(0x2A);
    TFT_WR_DATA(0x28);
    TFT_WR_DATA(0x08);
    TFT_WR_DATA(0x0E);
    TFT_WR_DATA(0x08);
    TFT_WR_DATA(0x54);
    TFT_WR_DATA(0XA9);
    TFT_WR_DATA(0x43);
    TFT_WR_DATA(0x0A);
    TFT_WR_DATA(0x0F);
    TFT_WR_DATA(0x00);
    TFT_WR_DATA(0x00);
    TFT_WR_DATA(0x00);
    TFT_WR_DATA(0x00);
    TFT_WR_REG(0XE1);    //Set Gamma
    TFT_WR_DATA(0x00);
    TFT_WR_DATA(0x15);
    TFT_WR_DATA(0x17);
    TFT_WR_DATA(0x07);
    TFT_WR_DATA(0x11);
    TFT_WR_DATA(0x06);
    TFT_WR_DATA(0x2B);
    TFT_WR_DATA(0x56);
    TFT_WR_DATA(0x3C);
    TFT_WR_DATA(0x05);
    TFT_WR_DATA(0x10);
    TFT_WR_DATA(0x0F);
    TFT_WR_DATA(0x3F);
    TFT_WR_DATA(0x3F);
    TFT_WR_DATA(0x0F);
    TFT_WR_REG(0x2B);
    TFT_WR_DATA(0x00);
    TFT_WR_DATA(0x00);
    TFT_WR_DATA(0x01);
    TFT_WR_DATA(0x3f);
    TFT_WR_REG(0x2A);
    TFT_WR_DATA(0x00);
    TFT_WR_DATA(0x00);
    TFT_WR_DATA(0x00);
    TFT_WR_DATA(0xef);
    TFT_WR_REG(0x11); //Exit Sleep
    TFT_WR_REG(0x29); //display on
    TFT_WriteReg(0x36,(1<<3)|(0<<7)|(1<<6)|(1<<5));
    TFT_Clear(BLACK);

}

void TFT_DrawPoint(uint16_t x,uint16_t y,uint16_t Color){
    TFT_SetCursor(x,y);
    TFT_WriteData_16Bit(Color);
}

void TFT_Fill(uint16_t sx,uint16_t sy,uint16_t ex,uint16_t ey,uint16_t color){
    uint16_t i,j;
    uint16_t width=ex-sx+1;
    uint16_t height=ey-sy+1;
    TFT_SetWindows(sx,sy,ex,ey);
    for(i=0;i<height;i++)
    {
        for(j=0;j<width;j++)
        TFT_WriteData_16Bit(color);
    }
    TFT_SetWindows(0,0,320-1,240-1);
}

